package breakthrough;

public class Board implements Comparable 
{
	public static final int BOARD_WIDTH = 8;
	public static final int BOARD_HEIGTH = 8;
	public static final int WHITE_PAWN = 'w';
	public static final int BLUE_PAWN = 'b';
	public static final int NULL_PAWN = '.';
	private char [][] boardTable = new char[BOARD_WIDTH][BOARD_HEIGTH];
	private char [][] previousBoardTable = new char[BOARD_WIDTH][BOARD_HEIGTH];
	private int boardValue;
	private Move boardMove = null;
	private boolean whiteWins = false;
	private boolean blueWins = false;
	
	/**
	 * Constructor
	 */
	public Board()
	{
		this.initializeTable();
	}
	
	/**
	 * Constructor
	 * @param aBoard
	 */
	public Board(Board aBoard)
	{
		setBoardTable(aBoard.getBoardTable(), false);
		this.boardValue = aBoard.getBoardValue();
		this.boardMove = aBoard.getBoardMove();
		this.whiteWins = aBoard.whiteWins();
		this.blueWins = aBoard.blueWins();
	}
	
	/**
	 * Constructor
	 * @param table
	 */
	public Board(char [][] table, Move aMove)
	{
		setBoardTable(table, false);
		this.boardMove = aMove;
	}
	
	/**
	 * Constructor
	 * @param table
	 */
	public Board(char [][] table, char [][] previousTable, Move aMove)
	{
		setBoardTable(table, false);
		setBoardTable(previousTable, true);
		this.boardMove = aMove;
	}
	
	/**
	 * Initializes the table.
	 */
	public void initializeTable()
	{
		this.boardValue = 0;
		this.boardMove = null;
		for (int row = 0; row < BOARD_WIDTH; row++)
		{
			for (int col = 0; col < BOARD_HEIGTH; col++)
			{
				if (row == 0 || row == 1)
					this.boardTable[row][col] = WHITE_PAWN;
				else if (row == 6 || row == 7)
					this.boardTable[row][col] = BLUE_PAWN;
				else
					this.boardTable[row][col] = NULL_PAWN;
			}
		}
	}
	
	/**
	 * If game over state is reached.
	 * @return
	 */
	public boolean hasGameOverState()
	{
		// Blues win.
		for (int i = 0; i < Board.BOARD_HEIGTH; i++)
		{
			if (this.boardTable[0][i] == Board.BLUE_PAWN)
				this.blueWins = true;
		}
		
		// Whites win.
		for (int i = 0; i < Board.BOARD_HEIGTH; i++)
		{
			if (this.boardTable[7][i] == Board.WHITE_PAWN)
				this.whiteWins = true;
		}
		
		return this.whiteWins || this.blueWins;
	}
	
	/**
	 * Updates the board with a new move.
	 * @param aMove
	 */
	public void updateWithMove(Move aMove)
	{
		// May not be necessary because the server always returns a valid move...as long as it doesn't bug!
		/*if (MoveManager.isValidMove(boardTable, source, destination, aPlayer))
		{
		}*/
		PawnPosition src = aMove.getSourcePosition();
		PawnPosition dest = aMove.getDestinationPosition();
		
		char sourceValue = this.boardTable[src.getRow()][src.getColumn()]; 
		this.boardTable[src.getRow()][src.getColumn()] = Board.NULL_PAWN;
		this.boardTable[dest.getRow()][dest.getColumn()] = sourceValue;
	}
	
	public boolean blueWins()
	{
		return this.blueWins;
	}
	
	public boolean whiteWins()
	{
		return this.whiteWins;
	}
	
	/**
	 * Getter boardTable
	 * @return
	 */
	public char[][] getBoardTable()
	{
		return this.boardTable;
	}
	
	/**
	 * Getter previousBoardTable
	 * @return
	 */
	public char[][] getPreviousBoardTable()
	{
		return this.boardTable;
	}
	
	/**
	 * Setter boardTable and previousBoardTable
	 * @param aTable
	 */
	public void setBoardTable(char [][] aTable, boolean previousBoard)
	{
		if (aTable != null)
		{
			for (int i = 0; i < BOARD_WIDTH; i++)
			{
				for (int j = 0; j < BOARD_HEIGTH; j++)
				{
					if (!previousBoard)
						this.boardTable[i][j] = aTable[i][j];
					else
						this.previousBoardTable[i][j] = aTable[i][j];
				}
			}
		}
	}
	
	/**
	 * Getter boardValue
	 * @return
	 */
	public int getBoardValue()
	{
		return this.boardValue;
	}
	
	/**
	 * Setter boardValue
	 * @param aValue
	 */
	public void setBoardValue(int aValue)
	{
		this.boardValue = aValue;
	}
	
	/**
	 * Getter for boardMove
	 * @return
	 */
	public Move getBoardMove()
	{
		return this.boardMove;
	}
	
	/**
	 * Setter for boardMove
	 * @param aMove
	 */
	public void setBoardMove(Move aMove)
	{
		this.boardMove = aMove;
	}
	
	/**
	 * Show board in console
	 */
	public void show()
	{
		for (int i = 0; i < BOARD_WIDTH; i++)
		{
			for (int j = 0; j < BOARD_HEIGTH; j++)
			{
				System.out.print(this.boardTable[i][j] + " ");
			}
			System.out.println();
		}
		System.out.println("Move: " + this.boardMove);
		System.out.println("Value: " + this.boardValue);
	}
	
	/**
	 * Show previous board in console
	 */
	public void showPrevious()
	{
		for (int i = 0; i < BOARD_WIDTH; i++)
		{
			for (int j = 0; j < BOARD_HEIGTH; j++)
			{
				System.out.print(this.previousBoardTable[i][j] + " ");
			}
			System.out.println();
		}
		System.out.println("---------");
	}

	@Override
	public int compareTo(Object arg0)
	{
		if (this.boardValue > ((Board)arg0).getBoardValue())
			return 1;
		if (this.boardValue < ((Board)arg0).getBoardValue())
			return -1;
		return 0;
	}
}
